package model

import (
	"database/sql"
	"fmt"
	"math/rand"
	"time"
	"wxpay/pkg/util"
)

// SubmchWithdraw struct is a row record of the submch_withdraw table in the wxpay database
type SubMchWithdraw struct {
	//[ 0] id                                             INT8                 null: false  primary: true   isArray: false  auto: false  col: INT8            len: -1      default: []
	ID int64 `gorm:"primary_key;column:id;type:INT8;"`
	//[ 1] mch_id                                         VARCHAR(32)          null: false  primary: false  isArray: false  auto: false  col: VARCHAR         len: 32      default: []
	MchID string `gorm:"column:mch_id;type:VARCHAR;size:32;"`
	//[ 2] sub_mch_id                                     VARCHAR(32)          null: false  primary: false  isArray: false  auto: false  col: VARCHAR         len: 32      default: []
	SubMchID string `gorm:"column:sub_mch_id;type:VARCHAR;size:32;"`
	//[ 3] out_request_no                                 VARCHAR(32)          null: false  primary: false  isArray: false  auto: false  col: VARCHAR         len: 32      default: []
	OutRequestNo string `gorm:"column:out_request_no;type:VARCHAR;size:32;"`
	//[ 4] wx_withdraw_id                                 VARCHAR(128)         null: true   primary: false  isArray: false  auto: false  col: VARCHAR         len: 128     default: []
	WxWithdrawID sql.NullString `gorm:"column:wx_withdraw_id;type:VARCHAR;size:128;"`
	//[ 5] biz_withdraw_id                                VARCHAR(32)          null: false  primary: false  isArray: false  auto: false  col: VARCHAR         len: 32      default: []
	BizWithdrawID string `gorm:"column:biz_withdraw_id;type:VARCHAR;size:32;"`
	//[ 6] amount                                         INT8                 null: false  primary: false  isArray: false  auto: false  col: INT8            len: -1      default: []
	Amount int64 `gorm:"column:amount;type:INT8;"`
	//[ 7] remark                                         VARCHAR(56)          null: true   primary: false  isArray: false  auto: false  col: VARCHAR         len: 56      default: []
	Remark sql.NullString `gorm:"column:remark;type:VARCHAR;size:56;"`
	//[ 8] bank_memo                                      VARCHAR(32)          null: true   primary: false  isArray: false  auto: false  col: VARCHAR         len: 32      default: []
	BankMemo sql.NullString `gorm:"column:bank_memo;type:VARCHAR;size:32;"`
	//[ 9] create_time                                    TIMESTAMPTZ          null: false  primary: false  isArray: false  auto: false  col: TIMESTAMPTZ     len: -1      default: []
	CreateTime time.Time `gorm:"column:create_time;type:TIMESTAMPTZ;"`
	//[10] update_time                                    TIMESTAMPTZ          null: false  primary: false  isArray: false  auto: false  col: TIMESTAMPTZ     len: -1      default: []
	UpdateTime time.Time `gorm:"column:update_time;type:TIMESTAMPTZ;"`
	//[11] status                                         VARCHAR(16)          null: false   primary: false  isArray: false  auto: false  col: VARCHAR         len: 16      default: []
	Status string `gorm:"column:status;type:VARCHAR;size:16;"`
	//[12] reason                                         VARCHAR(255)         null: true   primary: false  isArray: false  auto: false  col: VARCHAR         len: 255     default: []
	Reason  sql.NullString `gorm:"column:reason;type:VARCHAR;size:255;"`
	BrandID string         `gorm:"column:brand_id;type:VARCHAR;size:16;"`
}

// TableName sets the insert table name for this struct type
func (s *SubMchWithdraw) TableName() string {
	return "submch_withdraw"
}

func newWithdrawNo() string {
	//	申请编号生成规则 W+时间+8位随机数
	t := util.GetNow()
	s := rand.NewSource(t.UnixNano())
	r := rand.New(s)
	return "W" + t.Format(util.LayoutyyMMddHHmmss) + fmt.Sprintf("%08d", r.Intn(100000000))
}

func NewSubMchWithdraw(brandID string, mchID string, subMchID string, bizID string, amount int64, remark string, bankMemo string) *SubMchWithdraw {
	now := util.GetNow()
	return &SubMchWithdraw{
		OutRequestNo:  newWithdrawNo(),
		BrandID:       brandID,
		MchID:         mchID,
		SubMchID:      subMchID,
		BizWithdrawID: bizID,
		Amount:        amount,
		Remark:        util.AdaptNullString(remark),
		BankMemo:      util.AdaptNullString(bankMemo),
		Status:        WithdrawStatusAwait,
		CreateTime:    now,
		UpdateTime:    now,
	}
}

// 生成业务单号
func (s *SubMchWithdraw) GenOutRequestNo() {
	//	业务单号生成规则 W+时间+8位随机数
	t := util.GetNow()
	source := rand.NewSource(t.UnixNano())
	r := rand.New(source)
	s.OutRequestNo = "A" + t.Format(util.LayoutyyMMddHHmmss) + fmt.Sprintf("%08d", r.Intn(100000000))
}

// 更新微信单号
func (s *SubMchWithdraw) UpdateWxWithdrawID(wxID string) {
	t := util.GetNow()
	s.WxWithdrawID = util.AdaptNullString(wxID)
	s.Status = WithdrawStatusSubmitted
	s.UpdateTime = t
}

// UpdateStatus 更新提现状态，仅状态有变化才更新
func (s *SubMchWithdraw) UpdateStatus(status string, reason string) (updated bool) {
	if s.Status != status {
		t := util.GetNow()
		s.Status = status
		switch status {
		case WithdrawStatusClosed, WithdrawStatusFailed, WithdrawStatusRefunded:
			// 仅关单，失败，退票时有值
			s.Reason = util.AdaptNullString(reason)
		}
		s.UpdateTime = t
		updated = true
		return
	}
	return
}

// 受理成功
const WithdrawStatusCreated = "CREATE_SUCCESS"

// 提现成功
const WithdrawStatusSuccess = "SUCCESS"

// 提现失败
const WithdrawStatusFailed = "FAIL"

// 提现退票
const WithdrawStatusRefunded = "REFUND"

// 关单
const WithdrawStatusClosed = "CLOSE"

// 业务单已创建
const WithdrawStatusInit = "INIT"

// 业务单待提交
const WithdrawStatusAwait = "AWAIT"

// 业务单已提交
const WithdrawStatusSubmitted = "SUBMITTED"

// 检查提现状态是否终态
func (p *SubMchWithdraw) IsFinalState() bool {
	switch p.Status {
	case WithdrawStatusSuccess, WithdrawStatusFailed, WithdrawStatusRefunded, WithdrawStatusClosed:
		return true
	default:
		return false
	}
}
